/************************************************************
   Copyright 2008 Abhinav Pobbati

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*************************************************************/

#pragma once
#include "Havok4Xna/Physics/Dynamics/HkpDynamics.h"
#include "Havok4Xna/Physics/Collide/Agent/HkpAgent.h"
#include "Havok4Xna/Physics/Collide/Dispatch/HkpDispatch.h"

#pragma unmanaged
#include <Physics/Dynamics/Collide/hkpCollisionListener.h>
#include <Physics/Dynamics/Collide/hkpDynamicsContactMgr.h>
#include <Physics/Dynamics/Collide/hkpContactUpdater.h>
//#include <Physics/Dynamics/Collide/hkpReportContactMgr.h>
#include <Physics/Dynamics/Collide/hkpResponseModifier.h>
#include <Physics/Dynamics/Collide/hkpSimpleConstraintContactMgr.h>
#pragma managed

namespace Havok4Xna {
	ref class HkContactPoint;
	namespace Physics {
		namespace ConstraintSolver {
			ref class HkpContactPointProperties;
			ref class HkpSimpleContactConstraintAtom;
			ref class HkpContactProperties;
			ref class HkpSimpleContactConstraintData;
		}
		namespace Collide {
			ref class HkpContactMgr;
		}
	}
}

using Havok4Xna::HkContactPoint;
using Havok4Xna::Physics::Collide::HkpContactMgr;
using Havok4Xna::Physics::Collide::HkpContactMgrFactory;
using Havok4Xna::Physics::ConstraintSolver::HkpContactPointProperties;
using Havok4Xna::Physics::ConstraintSolver::HkpSimpleContactConstraintAtom;
using Havok4Xna::Physics::ConstraintSolver::HkpContactProperties;
using Havok4Xna::Physics::ConstraintSolver::HkpSimpleContactConstraintData;

namespace Havok4Xna {
	namespace Physics {
		namespace Dynamics {
			ref class HkpEntity;
			ref class HkpToiPointAddedEvent;
			ref class HkpManifoldPointAddedEvent;
			ref class HkpDynamicsContactMgr;
			
			public enum class HkpContactPointAccept : int {
				Accept = HK_CONTACT_POINT_ACCEPT,
				Reject = HK_CONTACT_POINT_REJECT
			};

			public ref class HkpContactPointAddedEvent : public INativeReference {
			/*public:
				DECLARE_PROPERTY_GETSET(HkpCdBody^, BodyA)
				DECLARE_PROPERTY_GETSET(HkpCdBody^, BodyB)
				DECLARE_PROPERTY_GETSET(HkpEntity^, CallbackFiredFrom)
				DECLARE_PROPERTY_GETSET(HkContactPoint^, ContactPoint)
				DECLARE_PROPERTY_GETSET(HkpGskCache^, GskCache)
				DECLARE_PROPERTY_GETSET(HkpContactPointProperties^, ContactPointProperties)
				DECLARE_PROPERTY_GET(HkpSimpleContactConstraintAtom^, Atom)
				DECLARE_PROPERTY_GETSET(float, ProjectedVelocity)
				DECLARE_PROPERTY_GETSET(HkpContactPointAccept, Status)

				int GetEntityIndex(HkpEntity ^entity);
				int GetNumExtendedUserDatas(HkpEntity ^entity);
				int GetExtendedUserDatas(HkpEntity ^entity, int numDatas);
				void SetExtendedUserDatas(HkpEntity ^entity, int numDatas);
				HkpToiPointAddedEvent ^AsToiEvent();
				HkpManifoldPointAddedEvent ^AsManifoldEvent();*/

			internal:
				HK_CLASS_INTERNALS(HkpContactPointAddedEvent, hkpContactPointAddedEvent)
			};

			public ref class HkpContactPointConfirmedEvent : public INativeReference {
			/*public:
				DECLARE_PROPERTY_GET(bool, IsToi)
				DECLARE_PROPERTY_GETSET(HkpSimpleContactConstraintAtom^, Atom)
				DECLARE_PROPERTY_GETSET(HkpCollidable^, CollidableA)
				DECLARE_PROPERTY_GETSET(HkpCollidable^, CollidableB)
				DECLARE_PROPERTY_GETSET(HkpEntity^, CallbackFiredFrom)
				DECLARE_PROPERTY_GETSET(HkContactPoint^, ContactPoint)
				DECLARE_PROPERTY_GETSET(HkpContactProperties^, ContactPointProperties)
				DECLARE_PROPERTY_GETSET(float, RotateNormal)
				DECLARE_PROPERTY_GETSET(float, ProjectedVelocity)
				DECLARE_PROPERTY_GETSET(HkpSimpleContactConstraintData^, ContactData)
				
				int GetEntityIndex(HkpEntity ^entity);
				int GetNumExtendedUserDatas(HkpEntity ^entity);
				int GetExtendedUserDatas(HkpEntity ^entity, int numDatas);
				void SetExtendedUserDatas(HkpEntity ^entity, int numDatas);*/
			
			internal:
				HK_CLASS_INTERNALS(HkpContactPointConfirmedEvent, hkpContactPointConfirmedEvent)
			};

			public ref class HkpContactPointRemovedEvent : public INativeReference {
			/*public:
				DECLARE_PROPERTY_GET(bool, IsToi)
				DECLARE_PROPERTY_GETSET(HkpEntity^, EntityA)
				DECLARE_PROPERTY_GETSET(HkpEntity^, EntityB)
				DECLARE_PROPERTY_GETSET(HkpEntity^, CallbackFiredFrom)
				DECLARE_PROPERTY_GETSET(hkContactPointId, ContactPointId)
				DECLARE_PROPERTY_GETSET(HkpContactPointProperties^, ContactPointProperties)
				DECLARE_PROPERTY_GET(HkpSimpleContactConstraintAtom^, Atom)

				int GetEntityIndex(HkpEntity ^entity);
				int GetNumExtendedUserDatas(HkpEntity ^entity);
				int GetExtendedUserDatas(HkpEntity ^entity, int numDatas);
				void SetExtendedUserDatas(HkpEntity ^entity, int numDatas);
				HkpToiPointAddedEvent ^AsToiEvent();
				HkpManifoldPointAddedEvent ^AsManifoldEvent();*/

			internal:
				HK_CLASS_INTERNALS(HkpContactPointRemovedEvent, hkpContactPointRemovedEvent)
			};

			public ref class HkpContactProcessEvent : public INativeReference {
			/*public:
				DECLARE_PROPERTY_GETSET(HkpEntity^, EntityA)
				DECLARE_PROPERTY_GETSET(HkpEntity^, EntityB)
				DECLARE_PROPERTY_GETSET(HkpEntity^, CallbackFiredFrom)
				DECLARE_PROPERTY_GETSET(hkContactPointId, ContactPointId)
				DECLARE_PROPERTY_GETSET(HkpContactPointProperties^, ContactPointProperties)
				DECLARE_PROPERTY_GET(HkpSimpleContactConstraintAtom^, Atom)
				DECLARE_PROPERTY_GETSET(HkpProcessCollisionData^, CollisionData)

				int GetEntityIndex(HkpEntity ^entity);
				int GetNumExtendedUserDatas(HkpEntity ^entity);
				int GetExtendedUserDatas(int contactPointIndex, HkpEntity ^entity, int numDatas);
				void SetExtendedUserDatas(int contactPointIndex, HkpEntity ^entity, int numDatas);
				int GetToiExtendedUserDatas(HkpEntity ^entity, int numDatas);
				void SetToiExtendedUserDatas(HkpEntity ^entity, int numDatas);

				HkpContactProcessEvent(HkpDynamicsContactMgr ^contactMgr, HkpCollidable ^a, HkpCollidable ^b, HkpProcessCollisionData ^cr);*/

			internal:
				HK_CLASS_INTERNALS(HkpContactProcessEvent, hkpContactProcessEvent)
			};

			public ref class HkpContactUpdateEvent : public INativeReference {
			internal:
				HK_CLASS_INTERNALS(HkpContactUpdateEvent, hkpContactUpdateEvent)
			};

			public ref class HkpToiPointAddedEvent : public INativeReference {
			internal:
				HK_CLASS_INTERNALS(HkpToiPointAddedEvent, hkpToiPointAddedEvent)
			};

			public interface class HkpCollisionListener : public INativeReference {
				void ContactPointAddedCallback(HkpContactPointAddedEvent ^evt);
				void ContactPointConfirmedCallback(HkpContactPointConfirmedEvent ^evt);
				void ContactPointRemovedCallback(HkpContactPointRemovedEvent ^evt);
				void ContactProcessCallback(HkpContactProcessEvent ^evt);
			};

			public ref class HkpContactUpdater : public INativeReference {
			internal:
				HK_CLASS_INTERNALS(HkpContactUpdater, hkpContactUpdater)
			};

			public ref class HkpDynamicsContactMgr : public HkpContactMgr {
			internal:
				HK_DERIVED_CLASS_INTERNALS(HkpDynamicsContactMgr, hkpDynamicsContactMgr, HkpContactMgr)
			};

			public ref class HkpManifoldPointAddedEvent : public INativeReference {
			internal:
				HK_CLASS_INTERNALS(HkpManifoldPointAddedEvent, hkpManifoldPointAddedEvent)
			};

			/*public ref class HkpReportContactMgr : public HkpDynamicsContactMgr {
			public:
				ref class Factory {

				};
			};*/

			public ref class HkpSimpleConstraintContactMgr : public HkpDynamicsContactMgr {
			public:
				ref class Factory : public HkpContactMgrFactory {
				internal:
					HK_DERIVED_CLASS_INTERNALS(Factory, hkpSimpleConstraintContactMgr::Factory, HkpContactMgrFactory)
				};

			internal:
				HK_DERIVED_CLASS_INTERNALS(HkpSimpleConstraintContactMgr, hkpSimpleConstraintContactMgr, HkpDynamicsContactMgr)
			};

			public ref class HkpResponseModifier : public INativeReference {
			internal:
				HK_CLASS_INTERNALS(HkpResponseModifier, hkpResponseModifier)
			};
		}
	}
}
